{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 测试Random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from types import GenericAlias\n",
    "from dataclasses import dataclass\n",
    "from abc import abstractmethod, ABC\n",
    "from __future__ import annotations\n",
    "from typing import Any, Callable, Tuple, TypeVar\n",
    "\n",
    "S = TypeVar(\"S\")\n",
    "T = TypeVar(\"T\")\n",
    "\n",
    "\n",
    "class RNG(ABC):\n",
    "    \n",
    "    @abstractmethod\n",
    "    def next_int(self) -> Tuple[int, RNG]:\n",
    "        pass\n",
    "\n",
    "\n",
    "@dataclass\n",
    "class SimpleRNG(RNG):\n",
    "    seed: int\n",
    "    def next_int(self) -> Tuple[int, RNG]:\n",
    "        new_seed = (self.seed * 0x5DEECE66D + 0xB) & 0xFFFFFFFFFFFF\n",
    "        next_RNG = SimpleRNG(new_seed)\n",
    "        n = int(new_seed >> 16)\n",
    "        return (n, next_RNG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "Rand = GenericAlias(Callable[[RNG], Tuple[S, RNG]], S)\n",
    "\n",
    "rand_int: Rand[int] = SimpleRNG.next_int\n",
    "\n",
    "def unit(s: S) -> Rand[S]:\n",
    "    return lambda rng: (s, rng)\n",
    "\n",
    "def map(rand: Rand[S], f: Callable[[S], T]) -> Rand[T]:\n",
    "    def helper(rng: RNG):\n",
    "        res, rng2 = rand(rng)\n",
    "        return (f(res), rng2)\n",
    "    return helper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "rand_non_negative_int: Rand[int] = map(rand_int, abs)\n",
    "rand_non_negative_even: Rand[int] = map(rand_int, lambda x: x - x % 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "b00d0533784e0bd7ec39dc1f12727fcf9021e9a985583666278f4fb55e7dfcf4"
  },
  "kernelspec": {
   "display_name": "Python 3.10.0 64-bit ('fppy2': conda)",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
